package mypazar.cartagoseagent;

import jason.environment.grid.Location;
import mypazar.agent.PersonAgent;
import mypazar.jenamodel.PazarRDFS;
import mypazar.jenamodel.PazarVocabulary;
import tr.edu.ege.seagent.planner.htn.Action;
import tr.edu.ege.seagent.planner.htn.ExecutionMethod;
import tr.edu.ege.seagent.planner.htn.Provision;
import cartago.ArtifactId;
import cartago.CartagoException;
import cartago.Op;
import cartago.Tuple;
import cartago.util.agent.CartagoBasicContext;
import cartago.util.agent.Percept;

import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;

/**
 * Action class of ACAskPrice.
 */
public class ACAskPrice extends Action {

	/**
	 * Ctx provision.
	 */
	@Provision
	private CartagoBasicContext Ctx;

	/**
	 * Returns the value of the Ctx provision.
	 */
	public CartagoBasicContext getCtx() {
		return this.Ctx;
	}

	/**
	 * Sets the value of the Ctx provision.
	 */
	public void setCtx(CartagoBasicContext Ctx) {
		this.Ctx = Ctx;
	}

	/**
	 * ArtifactId provision.
	 */
	@Provision
	private ArtifactId ArtifactId;

	/**
	 * Returns the value of the ArtifactId provision.
	 */
	public ArtifactId getArtifactId() {
		return this.ArtifactId;
	}

	/**
	 * Sets the value of the ArtifactId provision.
	 */
	public void setArtifactId(ArtifactId ArtifactId) {
		this.ArtifactId = ArtifactId;
	}

	/**
	 * Execution method.
	 */
	@ExecutionMethod
	public void execute() {

		Model beliefBase = (Model) getHeapValue(PersonAgent.BELIEF_BASE_ITEM_NAME);

		String PERSON_URI = PazarVocabulary.NS_URI
				+ getAgentIdentifier().toString().substring(0, 7);

		Location senderLoc = getCurrentLoc(beliefBase
				.createResource(PERSON_URI));

		CartagoBasicContext ctX = getCtx();
		ArtifactId artifactId = getArtifactId();

		try {
			ctX.focus(artifactId);
		} catch (CartagoException e) {
			e.printStackTrace();
		}

		try {
			ctX.doAction(artifactId, new Op("askAboutPrice"));
		} catch (CartagoException e) {
			e.printStackTrace();
		}
		Percept percept = null;

		int price = 0;

		// Wait for percept and receive price signal
		while (true) {
			try {
				percept = ctX.waitForPercept();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Tuple signal = percept.getSignal();
			if (signal.getLabel().equals("price")) {
				price = (Integer) signal.getContent(0);
			}
			if (price != 0) {
				break;
			}
		}

		String senderName = "salesman" + artifactId.getName().substring(5, 6);

		addProductPriceToBeliefBase(beliefBase, PERSON_URI, senderName, price,
				senderLoc);

	}

	/**
	 * Add product's price, sender and location informations into belief base
	 * 
	 * @param beliefBase
	 * @param personURI
	 * @param senderSmanName
	 * @param productPrice
	 * @param senderLoc
	 */
	private void addProductPriceToBeliefBase(Model beliefBase,
			String personURI, String senderSmanName, Integer productPrice,
			Location senderLoc) {

		String RECEIVED_PRICE_FROM_SMAN_URI = PazarVocabulary.RECEIVED_PRICE_URI
				+ senderSmanName.substring(8, 9);
		Resource resPerson = beliefBase.getResource(personURI);

		Resource receivedPriceNode = beliefBase
				.createResource(RECEIVED_PRICE_FROM_SMAN_URI,
						PazarRDFS.RECEIVED_PRICE_CLASS)
				.addProperty(beliefBase.getProperty(PazarVocabulary.PRICE_URI),
						Integer.toString(productPrice), XSDDatatype.XSDint)
				.addProperty(
						beliefBase.getProperty(PazarVocabulary.SENDER_URI),
						senderSmanName, XSDDatatype.XSDstring)
				.addProperty(
						beliefBase.getProperty(PazarVocabulary.SENDER_POSX_URI),
						Integer.toString(senderLoc.x), XSDDatatype.XSDint)
				.addProperty(
						beliefBase.getProperty(PazarVocabulary.SENDER_POSY_URI),
						Integer.toString(senderLoc.y), XSDDatatype.XSDint);

		resPerson.addProperty(
				beliefBase.getProperty(PazarVocabulary.RECEIVED_PRICE_URI),
				receivedPriceNode);
	}

	/**
	 * Gets agent's current location from belief base
	 * 
	 * @param beliefBase
	 * @param personURI
	 * @return
	 */
	private Location getCurrentLoc(Resource resPerson) {
		StmtIterator iterPos = resPerson.listProperties(ResourceFactory
				.createProperty(PazarVocabulary.POSITION_URI));
		if (iterPos.hasNext()) {
			Statement stmtPersonPos = iterPos.next();
			Resource resPersonStall = stmtPersonPos.getObject().asResource();
			// gets and returns location from given resource
			return new Location(resPersonStall
					.getProperty(
							ResourceFactory
									.createProperty(PazarVocabulary.POS_X_URI))
					.getLiteral().getInt(), resPersonStall
					.getProperty(
							ResourceFactory
									.createProperty(PazarVocabulary.POS_Y_URI))
					.getLiteral().getInt());

		} else
			return null;
	}

}
